package org.ala.tiktools.rocketmq;


/**
 * 雪花id生成器
 * <p>  64位
 *  0（标志位）| 41位（时间戳）| 10位（工作机器id）| 12位（序列号）
 *
 * @author ala
 * @date 2024-12-05 16:46
 */
public class SnowflakeIdGenerator {


    /**
     *  最高位永远是0，保证生成出来的id是>=0的
     *  <p> 如果不需要这个规则，那最高位也可以参与id生成
     */
    /**
     * 41位时间戳
     */
    static long MASK_TIMESTAMP = (~(~1l << 41)) << 22;
    /**
     * 10位机器id
     */
    static long MASK_NODE = (~(~1l << 10)) << 12;
    /**
     *  12位序列位
     */
    static long MASK_SEQUENCE = ~(~1l << 12);


    /**
     *  机器码
     *  <p> 0 ~ 1023
     */
    protected long nodeMask;
    /**
     *  上次生成时间戳
     */
    protected long lastTimestamp = System.currentTimeMillis();
    /**
     *  同一时间戳内的自增序列号
     */
    protected long sequence = 0l;
    /**
     *  同一对象的同步锁
     */
    protected final Object LOCK = new Object();


    private SnowflakeIdGenerator() {}
    /**
     *  构建id生成器
     */
    public static SnowflakeIdGenerator build(long node) {
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator();
        generator.nodeMask = (node << 12) & MASK_NODE;
        return generator;
    }


    /**
     *  生成id
     */
    public long id() {
        synchronized (LOCK) {
            long now = System.currentTimeMillis();

            //  如果序列号已经满了，轮训到下一个毫秒
            while (sequence == 1023 && now == System.currentTimeMillis()) {
            }
            if (now > lastTimestamp) {
                sequence = 0l;
            }

            //  0 | 41位时间戳 | 10位机器码 | 12位同一时间戳下自增序列码
            long time = (now << 22) & MASK_TIMESTAMP,
                 seq = sequence++;
            lastTimestamp = now;
            return time | nodeMask | seq;
        }
    }

}
